import CppHeaderParser
import os
# upper()：所有字母大写
# lower()：所有字母小写
# capitalize()：首字母大写，其他字母小写
# title()：每个单词首字母大写，其他小写

def getCppHeaderPublicMethod(filename):
    tmpfilename = filename.replace(".", "_")
    defpredix = "_SRC_MOCK_"
    enter = "\n"
    mockclassprefix = "CMock"
    mockmethodclassfix="CMockMethod"

    funprefix = ""

    mockclasscontent = ""
    mockmethondclasscontent=""
    cppclasscontent = ""
    defcontent = ""
    #输入需要打印的头文件
    hppcontent = ""
    cppcontent = ""
    testcasecontent=""

    finedef = defpredix+tmpfilename.upper()
    line = "#ifdef  "+finedef+enter
    hppcontent = hppcontent+line
    hppcontent = hppcontent +enter
    print(filename)
    cppHeader = CppHeaderParser.CppHeader(filename,encoding="utf-8")
    #classes=cppHeader.classes
# 打印每个类的信息
    for classname in cppHeader.classes.keys():
        mockclasscontent = ""
        mockmethondclasscontent = ""
        cppclasscontent = ""

        classdef = defpredix+classname.upper()
        line = "#ifdef "+classdef+enter
        mockclasscontent = mockclasscontent + line
        mockmethondclasscontent = mockmethondclasscontent + line
        cppclasscontent = cppclasscontent+line
        line = "#define "+classdef+enter
        defcontent = defcontent+line

        mockclassname = mockmethodclassfix+classname.capitalize()
        objname = "mock_cl"+mockclassname
        line ="static "+mockclassname+" *"+objname+"=nullptr;"+enter
        cppclasscontent = cppclasscontent + line
        paraobj = " p"+objname
        line = "void set"  + objname + "( const "+mockclassname+" * "+paraobj+"){" + enter
        cppclasscontent = cppclasscontent + line
        line = " " + objname + " = " + paraobj + ";" + "}" + enter
        cppclasscontent = cppclasscontent + line

        line = mockclassprefix+classname.capitalize()+"{"+enter
        line1 = mockmethodclassfix+classname.capitalize()+"{"+enter
        mockclasscontent = mockclasscontent+line
        mockmethondclasscontent = mockmethondclasscontent+line1

        line = "public:"+enter
        mockclasscontent = mockclasscontent + line
        mockmethondclasscontent = mockmethondclasscontent + line

        #print("------------类%s---------："%classname)
        for oneMethod in cppHeader.classes[classname]['methods']['public']:
            methodname = oneMethod['name']
            line = "#ifdef "+ classdef+"_"+methodname.upper()+ enter
            mockclasscontent = mockclasscontent + line
            mockmethondclasscontent = mockmethondclasscontent + line
            cppclasscontent = cppclasscontent+line

            line = "#define " + classdef+"_"+methodname.upper()+ enter
            defcontent = defcontent + line

            line = "  virtual "+funprefix+oneMethod['debug']+enter
            mockclasscontent = mockclasscontent + line

            first =""
            paralist = ""
            realparalist=''
            if len(oneMethod['parameters']):
                for oneParam in oneMethod['parameters']:
                    paralist = paralist+first+oneParam['type']+" "+oneParam['name']
                    #print(oneParam['name'], oneParam['type'], end='; ')
                    realparalist = realparalist+first+oneParam['name']
                    first=","
            line = "  MOCK_METHOD("+"("+oneMethod['rtnType']+"),"+oneMethod['name']+","+"("+paralist+"),"+"());"+enter
            mockmethondclasscontent =mockmethondclasscontent+line

            line =oneMethod['rtnType']+" "+classname+"::"+methodname+"("+paralist+")"+enter
            cppclasscontent = cppclasscontent + line
            line ="{"+enter
            cppclasscontent = cppclasscontent + line
            line = "  "+objname+"->"+oneMethod['name']+"("+ realparalist+");"+ enter
            cppclasscontent = cppclasscontent + line
            line = "}" + enter
            cppclasscontent = cppclasscontent + line

            line = "TEST("+methodname+",will_return_"+oneMethod['rtnType'].replace(",","_").replace(" ","_")+"_when_fun_run_success)"
            testcasecontent = testcasecontent+line
            line = "{" + enter
            testcasecontent = testcasecontent + line
            line = "" + enter
            testcasecontent = testcasecontent + line
            line = "}" + enter
            testcasecontent = testcasecontent + line

            line = "#endif" + enter
            mockclasscontent = mockclasscontent + line
            mockmethondclasscontent = mockmethondclasscontent + line
            cppclasscontent = cppclasscontent + line

        for oneMethod in cppHeader.classes[classname]['methods']['private']:
            methodname = oneMethod['name']
            # print('总: ', oneMethod['debug'])
            # print('函数名: ', oneMethod['name'])
            # print('返回类型: ', oneMethod['rtnType'])
            # print('参数: ', end='')
            # if len(oneMethod['parameters']):
            #     for oneParam in oneMethod['parameters']:
            #         print(oneParam['name'], oneParam['type'], end='; ')
            # print('\n')
            line = "TEST(" + methodname + ",will_return_" + oneMethod['rtnType'].replace(",", "_").replace(" ",
                                                                                                           "_") + "_when_fun_run_success)"
            testcasecontent = testcasecontent + line
            line = "{" + enter
            testcasecontent = testcasecontent + line
            line = "" + enter
            testcasecontent = testcasecontent + line
            line = "}" + enter
            testcasecontent = testcasecontent + line


        line = "}" + enter
        mockclasscontent = mockclasscontent + line
        mockmethondclasscontent = mockmethondclasscontent + line

        line = "#endif "  + enter
        mockclasscontent = mockclasscontent + line
        mockmethondclasscontent = mockmethondclasscontent + line
        cppclasscontent = cppclasscontent + line

        hppcontent =hppcontent+mockclasscontent+mockmethondclasscontent
        cppcontent = cppcontent +cppclasscontent
    line = "#endif" + enter
    hppcontent = hppcontent + line
    return hppcontent,cppcontent,defcontent,testcasecontent


# r'  -open for reading (default)
# 'w' -open for writing, truncating the file first
# 'x' -create a new file and open it for writing
# 'a' -open for writing, appending to the end of the file if it exists
# 'b' -binary mode
# 't' -text mode (default)
# '+' -open a disk file for updating (reading and writing)
# 'U' -universal newline mode (deprecated)
def  generate_file(filename,content):
    with open(filename, mode='w', encoding='utf-8') as file_obj:
        file_obj.write(content)

def genrate_stub(path,filenname,base=""):
    prefix = 'mock_'
    hpp_appendix = "Stub.h"
    cpp_appendix = "Stub.cc"
    srcfilename = os.path.join(path,filenname)
    list = filenname.split('.')
    print(path,filenname,base,list)
    hppfilename = base+prefix + list[0] + hpp_appendix
    cppfilename = base+prefix + list[0] + cpp_appendix
    deffilename = base+prefix + list[0] +"_define_"+ hpp_appendix
    testcasefilename = base+prefix + list[0] +"_TEST_"+ cpp_appendix
    print(hppfilename, cppfilename)

    hppcontent, cppcontent,defcontent,testcontent = getCppHeaderPublicMethod(srcfilename)
    #print(hppcontent, cppcontent)
    generate_file(hppfilename, hppcontent)
    generate_file(cppfilename, cppcontent)
    generate_file(deffilename, defcontent)
    generate_file(testcasefilename, testcontent)


def findAllFile(base):
    for root, ds, fs in os.walk(base):
        for f in fs:
            if f.endswith('.h'):
                fullname = os.path.join(root, f)
                yield fullname
def get_files_allpath(base):
    for filepath,dirnames,filenames in os.walk(base):
        for filename in filenames:
            print(os.path.join(filepath,filename))
def get_files(base):
    for filepath,dirnames,filenames in os.walk(base):
        for filename in filenames:
            print (filename)
def generate_stub_from_path(srcdir,desdir):
    for filepath,dirnames,filenames in os.walk(srcdir):
        for filename in filenames:
            print(filepath,filenames)
            genrate_stub(filepath,filename,desdir)
            #print (filename)
if __name__ == '__main__':

    # prefix = 'mock_'
    # hpp_appendix ="Stub.h"
    # cpp_appendix = "Stub.cc"
    # srcfilename = "test.h"
    # list = srcfilename.split('.')
    #
    # hppfilename = prefix+list[0]+hpp_appendix
    # cppfilename = prefix + list[0] + cpp_appendix
    # print(hppfilename,cppfilename)
    #
    # hppcontent,cppcontent = getCppHeaderPublicMethod(srcfilename)
    # print(hppcontent, cppcontent)
    # generate_file(hppfilename,hppcontent)
    # generate_file(cppfilename, cppcontent)
    basepath = "./stub/"
    try:
        File_Path = basepath
        print(File_Path)
        # 判断是否已经存在该目录
        if not os.path.exists(File_Path):
            # 目录不存在，进行创建操作
            os.makedirs(File_Path)  # 使用os.makedirs()方法创建多层目录
            print("目录新建成功：" + File_Path)
        else:
            print("目录已存在！！！")
    except BaseException as msg:
        print("新建目录失败：" + msg)

    #genrate_stub("test.h",basepath)
    generate_stub_from_path("./src","./stub/")
    #get_files("./src")
    # base = './'
    # for i in findAllFile(base):
    #     print(i)
    #findAllFile("./")